/*
 * Syntelos 'SX'
 * Copyright (C) 1998, 2007  John Pritchard.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 */
package syntelos.sx.methods.s;

import syntelos.sx.Response;
import syntelos.sx.Request;
import syntelos.sys.Capabilities;

import alto.io.Code;
import alto.io.Check;
import alto.io.Input;
import alto.io.Output;
import alto.io.Principal;
import alto.io.Uri;
import alto.lang.Buffer;
import alto.lang.Component;
import alto.lang.InputStream;
import alto.lang.Type;
import alto.sec.DN;
import alto.sec.Keys;
import alto.sec.pkcs.PKCS12;
import alto.sec.x509.AVA;
import alto.sec.x509.AVAKeyword;
import alto.sec.x509.X500Name;
import alto.sec.x509.X509Certificate;
import alto.sys.FileManager;
import alto.sys.Reference;

/**
 * Create user, return PKCS#12 certificate.  
 * 
 * <h3>Usage</h3>
 * 
 * Make a FORM POST to "/s/cert.pfx" to give the browser everything it
 * needs to install a new user RSA certificate.  Export the cert from
 * the browser for backup, or to use it otherwise.  (N.B. Backup the
 * keys to your account!)
 * 
 * The FORM POST parameters must include PASSWD and UID.  Optionally
 * also include personal identifying information as described in
 * {@link DN}.  Note that this operator will define DC and DNQ.
 * 
 * The PASSWD parameter is used only in the production of the returned
 * PKCS#12 certificate, and is not (otherwise) employed on the server
 * side.
 * 
 * The UID parameter identifies the account, and is relative to the DC
 * and DNQ of the request.
 * 
 * @see DN
 * @see syntelos.sys.Capabilities$UserCreate
 * @since 1.6
 */
public class Post
    extends Abstract
{
    public final static String CanonicalPath = "/s/cert.pfx"; 

    public final static void Create(Request req, Response rep, java.lang.String passwd, X500Name name)
        throws java.io.IOException
    {
        if (null != passwd && null != name){
            String uid = name.getUID();
            if (null == uid || (alto.io.Principal.Tools.IsNotName(uid))){
                rep.setStatusBadRequest();
                return ;
            }
            else {
                /*
                 * Generate & write RSA Key Pair
                 */
                Keys keys = Keys.Tools.GetCreate(uid,name);
                {
                    boolean close = false;
                    java.io.OutputStream out = rep.getOutputStream();
                    if (null == out){
                        close = true;
                        out = rep.openOutputStream();
                    }
                    try {
                        PKCS12 pfx = keys.createPfx("RSA",passwd);
                        pfx.encode(out,passwd);
                    }
                    catch (java.security.cert.CertificateException exc){
                        throw new alto.sys.Error(exc);
                    }
                    finally {
                        if (close)
                            out.close();
                    }
                }
                rep.setStatusCreated();
                return ;
            }
        }
        else {
            rep.setStatusBadRequest();
            return ;
        }
    }

    public Post(){
        super();
    }


    @Code(Check.TODO)
    public void respond(Request req)
        throws java.io.IOException,
               java.lang.InterruptedException
    {
        super.respond(req);
        if (this.isAuthenticated(Capabilities.UserCreate.Instance)){
            Uri uri = req.getUri();
            if (CanonicalPath.equals(uri.getPath())){
                String keys[] = uri.getQueryKeys();
                if (null != keys){
                    DN dname = new DN();
                    String passwd = null;
                    for (int cc = 0, count = keys.length; cc < count; cc++){
                        String name = keys[cc];
                        String value = uri.getQuery(name);
                        if (!dname.put(name,value)){
                            if ("password".equalsIgnoreCase(name)){
                                passwd = value;
                            }
                        }
                    }
                    if (null != passwd && dname.hasUID()){

                        dname.updateFromFileManager();
                        X500Name name = new X500Name(dname.toString());
                        Create(req,this,passwd,name);
                        return;
                    }
                }
            }
            this.setStatusBadRequest();
        }
        else
            this.setStatusUnauthorized();
    }
}
